<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插入标记(1)</title>
</head>
<body>
<div id="app">
    <p>This is a <strong>innerHTML</strong> example</p>
    <ul>
        <li class="item">item1</li>
        <li class="item">item2</li>
        <li class="item">item3</li>
    </ul>
    <p class="insert">
        <span>HW</span>
        <span>HZ</span>
    </p>
</div>
</body>
<script>
/** 1.DOM 虽然已经为操纵节点提供了很多 API，但向文档中一次性插入大量 HTML 时还是比较麻烦。相比先创建一堆节点，再把它们以正确的顺序连接起来，
 *    直接插入一个 HTML 字符串要简单（快速）得多。
 * **/
/** 2.innerHTML 属性
 *    a.在读取 innerHTML 属性时，会返回元素所有后代的 HTML 字符串，包括元素、注释和文本节点。
 *    b.在写入 innerHTML 时，则会根据提供的字符串值以新的 DOM 子树替代元素中原来包含的所有节点。
 *    c.实际返回的文本内容会因浏览器而不同。IE 和 Opera 会把所有元素标签转换为大写，而 Safari、Chrome 和 Firefox
 *      则会按照文档源代码的格式返回，包含空格和缩进。
 *    d.在写入模式下，赋给 innerHTML 属性的值会被解析为 DOM 子树，并替代元素之前的所有节点。因为所赋的值默认为 HTML，
 *      所以其中的所有标签都会以浏览器处理 HTML 的方式转换为元素（同样，转换结果也会因浏览器不同而不同）。如果赋值中不包
 *      含任何 HTML 标签，则直接生成一个文本节点。
 *    e.因为浏览器会解析设置的值，所以给 innerHTML 设置包含 HTML 的字符串时，结果会大不一样。
 如下所示：
 * **/
 function checkInnerHTML(){
     let divDOM = document.getElementById("app");
     console.log(divDOM.innerHTML);
     setTimeout(function(){
         divDOM.innerHTML = "<h1>Hello World</h1>"
     },5000);
}
// checkInnerHTML();

/** 3.旧 IE 中的 innerHTML
 *     a.在所有现代浏览器中，通过 innerHTML 插入的<script>标签是不会执行的。而在 IE8 及之前的版本中，只要这样插入的<script>
 *       元素指定了 defer 属性，且<script>之前是“受控元素”（scopedelement），那就是可以执行的。<script>元素与<style>或注
 *       释一样，都是“非受控元素”（NoScopeelement），也就是在页面上看不到它们。IE 会把 innerHTML 中从非受控元素开始的内容都
 *       删掉，
 *     b.在 IE 中，通过 innerHTML 插入<style>也会有类似的问题。多数浏览器支持使用 innerHTML 插 入<style>元素,但在 IE8 及
 *       之前的版本中，<style>也被认为是非受控元素，所以必须前置一个受控元素：
 * **/

/** 4.outerHTML 属性
 *     a.读取 outerHTML 属性时，会返回调用它的元素（及所有后代元素）的 HTML 字符串。在写入outerHTML 属性时，调用它的元素会被
 *       传入的 HTML 字符串经解释之后生成的 DOM 子树取代。
 *     b.浏览器因解析和解释 HTML 代码的机制不同，返回的字符串也可能不同。（跟 innerHTML 的情况是一样的。）
 * **/
function checkOuterHTML(){
    let ulDOM = document.getElementsByTagName('ul')[0];
    console.log(ulDOM.outerHTML);//"<ul>......</ul>
    ulDOM.outerHTML = '<p>Hello outerHTML</p>'
}
// checkOuterHTML();

/** 5.insertAdjacentHTML()与insertAdjacentText()
 *    a.关于插入标签的最后两个新增方法是 insertAdjacentHTML()和 insertAdjacentText()。这两个方法最早源自 IE，它们都接收两
 *      个参数：要插入标记的位置和要插入的 HTML 或文本。第一个参数必须是下列值中的一个：
 *      + "beforebegin"，插入当前元素前面，作为前一个同胞节点；
 *      + "afterbegin"，插入当前元素内部，作为新的子节点或放在第一个子节点前面；
 *      + "beforeend"，插入当前元素内部，作为新的子节点或放在最后一个子节点后面；
 *      + "afterend"，插入当前元素后面，作为下一个同胞节点；
 *      + "begin"类比为"<div>","after"类比为"</di>"
 *    b.注意这几个值是不区分大小写的。第二个参数会作为 HTML 字符串解析（与 innerHTML 和outerHTML 相同）或者作为纯文本解析
 *     （与 innerText 和 outerText 相同）。如果是 HTML，则会在解析出错时抛出错误。
 * **/
function checkInsertAdjacent(){
    let pDOM = document.getElementsByClassName('insert')[0];
    // 1.作为当前节点的前一个同胞节点插入
    pDOM.insertAdjacentHTML('beforebegin',"<p>Hello beforebegin</p>");
    pDOM.insertAdjacentText('beforebegin',"hello beforebegin");
    // 2.作为当前节点的第一个子节点插入
    pDOM.insertAdjacentHTML('afterbegin','<p>Hello afterbegin</p>');
    pDOM.insertAdjacentText('afterbegin','Hello afterbegin');
    // 3.作为当前节点的最后一个子节点插入
    pDOM.insertAdjacentHTML("beforeend",'<p> Hello beforeend</p>');
    pDOM.insertAdjacentText("beforeend",'Hello beforeend');
    // 4.作为当前节点的后一个同胞节点插入
    pDOM.insertAdjacentHTML('afterend','<p>Hello afterend</p>');
    pDOM.insertAdjacentText('afterend','Hello afterend');
}
checkInsertAdjacent();
</script>
</html>